/**
 * 
 */
package com.nari.sink.dao;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import com.nari.coreframe.dao.hibernate3.GenericDaoImpl;
import com.nari.platform.model.PageCond;
import com.nari.platform.model.ResultWithPageCond;
import com.nari.platform.utils.NumberSystemConversion;
import com.nari.sink.bo.ISinkerStandardDict;

/**
 * 
 * @author Xiaopeng
 * @date 2014-4-15
 */
public class SinkerStandardDictDaoImpl extends GenericDaoImpl<ISinkerStandardDict, String> 
		implements ISinkerStandardDictDao {

	/**
	 * 分页查询散热器型号字典
	 * @param dictSerious
	 * @param sinkType
	 * @param brand
	 * @param pageCond
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-15
	 */
	@SuppressWarnings("unchecked")
	public ResultWithPageCond<ISinkerStandardDict> querySinkerDictPage(String dictSerious, 
			String sinkType, String brand, PageCond pageCond) throws Exception {
		Criteria listCriteria = this.getCurrentSession().createCriteria(ISinkerStandardDict.class);
		Criteria countCriteria = this.getCurrentSession().createCriteria(ISinkerStandardDict.class);
		//型号字典编号
		if(dictSerious!=null && !"".equals(dictSerious.trim())) {
			listCriteria.add(Restrictions.ilike("dictSerious", dictSerious.toLowerCase(), MatchMode.ANYWHERE));
			countCriteria.add(Restrictions.ilike("dictSerious", dictSerious.toLowerCase(), MatchMode.ANYWHERE));
		}
		//型号
		if(sinkType!=null && !"".equals(sinkType.trim())) {
			listCriteria.add(Restrictions.ilike("sinkType", sinkType.toLowerCase(), MatchMode.ANYWHERE));
			countCriteria.add(Restrictions.ilike("sinkType", sinkType.toLowerCase(), MatchMode.ANYWHERE));
		}
		//品牌
		if(brand!=null && !"".equals(brand.trim())) {
			listCriteria.add(Restrictions.ilike("brand", brand.toLowerCase(), MatchMode.ANYWHERE));
			countCriteria.add(Restrictions.ilike("brand", brand.toLowerCase(), MatchMode.ANYWHERE));
		}
		//统计结果集个数
		int total = ((Long)countCriteria.setProjection(Projections.rowCount()).list().get(0)).intValue();
		//结果集排序
		listCriteria.addOrder(Order.desc("updateTime")).addOrder(Order.asc("dictSerious"));
		//结果集分页
		listCriteria.setFirstResult(pageCond.getStart()).setMaxResults(pageCond.getLimit());
		//构造返回类型
		pageCond.setTotal(total);
		ResultWithPageCond<ISinkerStandardDict> sinkerPage = new ResultWithPageCond<ISinkerStandardDict>();
		sinkerPage.setList(listCriteria.list());
		sinkerPage.setPageCond(pageCond);
		return sinkerPage;
	}
	
	/**
	 * 根据标准散热器主要匹配参数（型号、中心距）统计符合匹配结果的型号数量
	 * @param sinkType
	 * @param sinkCenDis
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-18
	 */
	public int countSinkerDictPrimaryAdapter(String sinkType, double sinkCenDis) throws Exception {
		String hsql = "select count(*) from ISinkerStandardDict ssd " +
				"where ssd.sinkType='"+sinkType+"'";
		//中心距误差匹配，误差范围±15
		BigDecimal sinkCenDisStart = new BigDecimal(sinkCenDis).subtract(new BigDecimal("15"));
		BigDecimal sinkCenDisEnd = new BigDecimal(sinkCenDis).add(new BigDecimal("15"));
		hsql += " and ssd.sinkCenDis between :startValue and :endValue";
		Query query = this.getCurrentSession().createQuery(hsql);
		query.setBigDecimal("startValue", sinkCenDisStart).setBigDecimal("endValue", sinkCenDisEnd);
		return ((Long)query.uniqueResult()).intValue();
	}
	
	/**
	 * 根据标准散热器主要匹配参数（型号、中心距）查询符合匹配结果的型号列表
	 * @param sinkType
	 * @param sinkCenDis
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-18
	 */
	@SuppressWarnings("unchecked")
	public List<ISinkerStandardDict> querySinkerDictPrimaryAdapterList(String sinkType, 
			double sinkCenDis) throws Exception {
		String hsql = "from ISinkerStandardDict ssd " +
				"where ssd.sinkType='"+sinkType+"'";
		//中心距误差匹配，误差范围±15
		BigDecimal sinkCenDisStart = new BigDecimal(sinkCenDis).subtract(new BigDecimal("15"));
		BigDecimal sinkCenDisEnd = new BigDecimal(sinkCenDis).add(new BigDecimal("15"));
		hsql += " and ssd.sinkCenDis between :startValue and :endValue";
		Query query = this.getCurrentSession().createQuery(hsql);
		query.setBigDecimal("startValue", sinkCenDisStart).setBigDecimal("endValue", sinkCenDisEnd);
		return query.list();
	}
	
	/**
	 * 根据标准散热器主要参数匹配结果（标准散热器UID列表）、次要匹配参数（品牌、尺寸[高、宽、长]、
	 * 单片功率）统计符合匹配结果的型号数量
	 * @param primaryAdapterUIDList 散热器主要参数匹配结果
	 * 说明：若主要参数匹配结果为空，则不执行次要参数匹配，并返回零结果集
	 * @param brand
	 * @param sinkHeight
	 * @param sinkWidth
	 * @param sinkLength
	 * @param calPower
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-18
	 */
	public int countSinkerDictSecondaryAdapter(List<String> primaryAdapterUIDList, String brand, 
			double sinkHeight, double sinkWidth, double sinkLength, double calPower) throws Exception {
		int adapterResultNum = 0;
		if(primaryAdapterUIDList!=null && primaryAdapterUIDList.size()>0) {
			String hsql = "select count(*) from ISinkerStandardDict ssd " +
					"where ssd.id in(";
			for(int index=0; index<primaryAdapterUIDList.size(); index++) {
				String sinkerDictUID = primaryAdapterUIDList.get(index);
				hsql += "'" + sinkerDictUID + "'";
				if(index < primaryAdapterUIDList.size()-1) {
					hsql += ",";
				}
			}
			hsql += ")";
			//品牌
			if(brand!=null && !"".equals(brand)) {
				hsql += " and ssd.brand='"+brand+"'";
			}
			//散热器高
			if(NumberSystemConversion.compareFloatValue(sinkHeight, 0) > 0) {
				hsql += " and ssd.sinkHeight between :sinkHeightStart and :sinkHeightEnd";
			}
			//散热器宽
			if(NumberSystemConversion.compareFloatValue(sinkWidth, 0) > 0) {
				hsql += " and ssd.sinkWidth between :sinkWidthStart and :sinkWidthEnd";
			}
			//散热器长
			if(NumberSystemConversion.compareFloatValue(sinkLength, 0) > 0) {
				hsql += " and ssd.sinkLength between :sinkLengthStart and :sinkLengthEnd";
			}
			//单片功率
			if(NumberSystemConversion.compareFloatValue(calPower, 0) > 0) {
				hsql += " and ssd.calPower between :calPowerStart and :calPowerEnd";
			}
			Query query = this.getCurrentSession().createQuery(hsql);
			//散热器高误差匹配，误差范围±15
			if(NumberSystemConversion.compareFloatValue(sinkHeight, 0) > 0) {
				BigDecimal sinkHeightStart = new BigDecimal(sinkHeight).subtract(new BigDecimal("15"));
				BigDecimal sinkHeightEnd = new BigDecimal(sinkHeight).add(new BigDecimal("15"));
				query.setBigDecimal("sinkHeightStart", sinkHeightStart)
						.setBigDecimal("sinkHeightEnd", sinkHeightEnd);
			}
			//散热器宽误差匹配，误差范围±15
			if(NumberSystemConversion.compareFloatValue(sinkWidth, 0) > 0) {
				BigDecimal sinkWidthStart = new BigDecimal(sinkWidth).subtract(new BigDecimal("15"));
				BigDecimal sinkWidthEnd = new BigDecimal(sinkWidth).add(new BigDecimal("15"));
				query.setBigDecimal("sinkWidthStart", sinkWidthStart)
						.setBigDecimal("sinkWidthEnd", sinkWidthEnd);
			}
			//散热器长误差匹配，误差范围±15
			if(NumberSystemConversion.compareFloatValue(sinkLength, 0) > 0) {
				BigDecimal sinkLengthStart = new BigDecimal(sinkLength).subtract(new BigDecimal("15"));
				BigDecimal sinkLengthEnd = new BigDecimal(sinkLength).add(new BigDecimal("15"));
				query.setBigDecimal("sinkLengthStart", sinkLengthStart)
						.setBigDecimal("sinkLengthEnd", sinkLengthEnd);
			}
			//散热器单片功率误差匹配，误差范围±15
			if(NumberSystemConversion.compareFloatValue(calPower, 0) > 0) {
				BigDecimal calPowerStart = new BigDecimal(calPower).subtract(new BigDecimal("15"));
				BigDecimal calPowerEnd = new BigDecimal(calPower).add(new BigDecimal("15"));
				query.setBigDecimal("calPowerStart", calPowerStart)
						.setBigDecimal("calPowerEnd", calPowerEnd);
			}
			adapterResultNum = ((Long)query.uniqueResult()).intValue();
		}
		return adapterResultNum;
	}
	
	/**
	 * 根据标准散热器主要参数匹配结果（标准散热器UID列表）、次要匹配参数（品牌、尺寸[高、宽、长]、
	 * 单片功率）查询符合匹配结果的型号列表
	 * @param primaryAdapterUIDList 散热器主要参数匹配结果
	 * 说明：若主要参数匹配结果为空，则不执行次要参数匹配，并返回零结果集
	 * @param brand
	 * @param sinkHeight
	 * @param sinkWidth
	 * @param sinkLength
	 * @param calPower
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-18
	 */
	@SuppressWarnings("unchecked")
	public List<ISinkerStandardDict> querySinkerDictSecondaryAdapterList(List<String> primaryAdapterUIDList, 
			String brand, double sinkHeight, double sinkWidth, double sinkLength, 
			double calPower) throws Exception {
		List<ISinkerStandardDict> adapterResultList = null;
		if(primaryAdapterUIDList!=null && primaryAdapterUIDList.size()>0) {
			String hsql = "from ISinkerStandardDict ssd " +
					"where ssd.id in(";
			for(int index=0; index<primaryAdapterUIDList.size(); index++) {
				String sinkerDictUID = primaryAdapterUIDList.get(index);
				hsql += "'" + sinkerDictUID + "'";
				if(index < primaryAdapterUIDList.size()-1) {
					hsql += ",";
				}
			}
			hsql += ")";
			//品牌
			if(brand!=null && !"".equals(brand)) {
				hsql += " and ssd.brand='"+brand+"'";
			}
			//散热器高
			if(NumberSystemConversion.compareFloatValue(sinkHeight, 0) > 0) {
				hsql += " and ssd.sinkHeight between :sinkHeightStart and :sinkHeightEnd";
			}
			//散热器宽
			if(NumberSystemConversion.compareFloatValue(sinkWidth, 0) > 0) {
				hsql += " and ssd.sinkWidth between :sinkWidthStart and :sinkWidthEnd";
			}
			//散热器长
			if(NumberSystemConversion.compareFloatValue(sinkLength, 0) > 0) {
				hsql += " and ssd.sinkLength between :sinkLengthStart and :sinkLengthEnd";
			}
			//单片功率
			if(NumberSystemConversion.compareFloatValue(calPower, 0) > 0) {
				hsql += " and ssd.calPower between :calPowerStart and :calPowerEnd";
			}
			Query query = this.getCurrentSession().createQuery(hsql);
			//散热器高误差匹配，误差范围±15
			if(NumberSystemConversion.compareFloatValue(sinkHeight, 0) > 0) {
				BigDecimal sinkHeightStart = new BigDecimal(sinkHeight).subtract(new BigDecimal("15"));
				BigDecimal sinkHeightEnd = new BigDecimal(sinkHeight).add(new BigDecimal("15"));
				query.setBigDecimal("sinkHeightStart", sinkHeightStart)
						.setBigDecimal("sinkHeightEnd", sinkHeightEnd);
			}
			//散热器宽误差匹配，误差范围±15
			if(NumberSystemConversion.compareFloatValue(sinkWidth, 0) > 0) {
				BigDecimal sinkWidthStart = new BigDecimal(sinkWidth).subtract(new BigDecimal("15"));
				BigDecimal sinkWidthEnd = new BigDecimal(sinkWidth).add(new BigDecimal("15"));
				query.setBigDecimal("sinkWidthStart", sinkWidthStart)
						.setBigDecimal("sinkWidthEnd", sinkWidthEnd);
			}
			//散热器长误差匹配，误差范围±15
			if(NumberSystemConversion.compareFloatValue(sinkLength, 0) > 0) {
				BigDecimal sinkLengthStart = new BigDecimal(sinkLength).subtract(new BigDecimal("15"));
				BigDecimal sinkLengthEnd = new BigDecimal(sinkLength).add(new BigDecimal("15"));
				query.setBigDecimal("sinkLengthStart", sinkLengthStart)
						.setBigDecimal("sinkLengthEnd", sinkLengthEnd);
			}
			//散热器单片功率误差匹配，误差范围±15
			if(NumberSystemConversion.compareFloatValue(calPower, 0) > 0) {
				BigDecimal calPowerStart = new BigDecimal(calPower).subtract(new BigDecimal("15"));
				BigDecimal calPowerEnd = new BigDecimal(calPower).add(new BigDecimal("15"));
				query.setBigDecimal("calPowerStart", calPowerStart)
						.setBigDecimal("calPowerEnd", calPowerEnd);
			}
			adapterResultList = query.list();
		}
		return adapterResultList;
	}
	
	/**
	 * 根据散热器特征信息查询对应型号参数的标准散热器列表
	 * 散热器匹配原则：
	 * 优先级一：主要参数匹配，包括型号、中心距
	 * 优先级二：次要匹配参数，包括品牌、散热器尺寸（高、宽、长）、单片功率
	 * 说明：按照优先级从高到低的结果集最少的匹配原则，结果集越少，说明匹配精确度越高；
	 * 相应的数据冗余度可能越高，即同一型号参数的散热器因为参数等误差未正确匹配
	 * @param sinkerDict
	 * @return
	 * 返回结果说明：
	 * 1、结果集为空或结果集个数为0，说明字典库不存在此型号参数的标准散热器，视为正确匹配
	 * 2、结果集个数为1，说明字典库已存在此型号参数的标准散热器，也视为正确匹配
	 * 3、结果集个数大于1，说明字典库存在多个同种类型参数的标准散热器，视为匹配异常
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-18
	 */
	public List<ISinkerStandardDict> queryByCharacteristicInfo(ISinkerStandardDict sinkerDict) throws Exception {
		List<ISinkerStandardDict> adapterList = null;
		//主要参数匹配
		List<ISinkerStandardDict> primaryAdapterList = this.querySinkerDictPrimaryAdapterList(sinkerDict.getSinkType(), sinkerDict.getSinkCenDis());
		if(primaryAdapterList.size() == 1) {
			adapterList = primaryAdapterList;
		} else if(primaryAdapterList.size() > 1) {
			//在主要参数匹配的基础上进行次要参数匹配
			List<String> primaryAdapterUIDList = new ArrayList<String>();
			for(String primaryAdapterUID: primaryAdapterUIDList) {
				primaryAdapterUIDList.add(primaryAdapterUID);
			}
			//次要参数匹配
			List<ISinkerStandardDict> secondaryAdapterList = this.querySinkerDictSecondaryAdapterList(primaryAdapterUIDList, 
					sinkerDict.getBrand(), sinkerDict.getSinkHeight(), sinkerDict.getSinkWidth(), 
					sinkerDict.getSinkLength(), sinkerDict.getSinkCenDis());
			//次要参数匹配结果为空，则匹配结果无法选择，则返回主要参数匹配结果
			if(secondaryAdapterList==null || secondaryAdapterList.size()==0) {
				adapterList = primaryAdapterList;
			}
			//次要参数匹配结果集个数大于1，则匹配结果无法选择，但视为对主要参数匹配结果的范围精确缩小
			if(secondaryAdapterList!=null && secondaryAdapterList.size()>1) {
				adapterList = secondaryAdapterList;
			}
			//次要参数匹配结果集个数为1，即为精确匹配
			if(secondaryAdapterList!=null && secondaryAdapterList.size()==1) {
				adapterList = secondaryAdapterList;
			}
		}
		return adapterList;
	}
}
